<!-- 
在 Vue 3 中，过渡和动画是增强用户体验的重要特性。通过使用 Vue 的内置过渡组件，可以轻松地为元素的插入、删除和更新添加动画效果。以下是对 Vue 3 中过渡和动画的说明总结：
  1. 过渡组件
  Vue 提供了  <transition>  组件，用于包裹需要添加过渡效果的元素。它可以用于单个元素或组件的进入和离开时的过渡效果。

  基本用法：
  vue
  <template>
    <transition name="fade">
      <div v-if="show">Hello, Vue 3!</div>
    </transition>
    <button @click="show = !show">Toggle</button>
  </template>

  <script>
  export default {
    data() {
      return {
        show: true
      };
    }
  };
  </script>

  <style>
  .fade-enter-active, .fade-leave-active {
    transition: opacity 0.5s;
  }
  .fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
    opacity: 0;
  }
  </style>
  2. 过渡类名
  Vue 通过类名来控制过渡效果。可以使用以下类名：
  -  name-enter-active ：进入时的过渡效果
  -  name-leave-active ：离开时的过渡效果
  -  name-enter ：进入时的初始状态
  -  name-leave-to ：离开时的结束状态

  3. 动画库的支持
  Vue 3 支持与 CSS 动画库（如 Animate.css）结合使用。只需将库的类名添加到  <transition>  的  name  属性中，就可以轻松实现动画效果。

  4. JavaScript 钩子
  除了 CSS 过渡，Vue 还支持使用 JavaScript 钩子来控制过渡效果。可以在  <transition>  组件上使用以下钩子：
  -  before-enter 
  -  enter 
  -  leave 
  -  after-enter 
  -  after-leave 

  示例：
  vue
  <template>
    <transition @before-enter="beforeEnter" @enter="enter" @leave="leave">
      <div v-if="show">Hello, Vue 3!</div>
    </transition>
    <button @click="show = !show">Toggle</button>
  </template>

  <script>
  export default {
    data() {
      return {
        show: true
      };
    },
    methods: {
      beforeEnter(el) {
        // 进入前的操作
      },
      enter(el, done) {
        // 进入中的操作
        done(); // 必须调用 done() 来结束过渡
      },
      leave(el, done) {
        // 离开中的操作
        done(); // 必须调用 done() 来结束过渡
      }
    }
  };
  </script>
  5. 过渡的应用场景
  - 元素的显示和隐藏：如模态框、提示框等。
  - 列表的增删：如动态列表中的项的添加和删除。
  - 路由切换：在页面间切换时的过渡效果。

  总结
  在 Vue 3 中，通过  <transition>  组件和 CSS 类名，开发者可以轻松地为元素添加过渡和动画效果。结合 JavaScript 钩子，开发者可以实现更复杂的动画效果。合理使用过渡和动画可以极大地提升用户体验，使应用更加生动和吸引人。
-->
<template>
  <div class="app">
    <h3>1. transition动画</h3>
    <div class="transition-container">
      <transition name="transition-name">
        <h2 v-if="isShow">Hello transition</h2>
      </transition>
    </div>

    <h3>2. animation动画</h3>
    <div class="animation-container">
      <transition name="animation-name">
        <h3 v-if="isShow">
          在 Vue 3 中，过渡和动画是增强用户体验的重要特性。通过使用 Vue
          的内置过渡组件，可以轻松地为元素的插入、删除和更新添加动画效果。以下是对
          Vue 3 中过渡和动画的说明总结： 总结 在 Vue 3 中，通过 transition
          组件和 CSS 类名，开发者可以轻松地为元素添加过渡和动画效果。结合
          JavaScript
          钩子，开发者可以实现更复杂的动画效果。合理使用过渡和动画可以极大地提升用户体验，使应用更加生动和吸引人
        </h3>
      </transition>
    </div>

    <h3>3. 03_动画属性设置</h3>
    <div class="animation-container-one">
      <transition name="animation-name-one">
        <h3 v-if="isShow">
          在 Vue 3 中，过渡和动画是增强用户体验的重要特性。通过使用 Vue
          的内置过渡组件，可以轻松地为元素的插入、删除和更新添加动画效果。以下是对
          Vue 3 中过渡和动画的说明总结： 总结 在 Vue 3 中，通过 transition
          组件和 CSS 类名，开发者可以轻松地为元素添加过渡和动画效果。结合
          JavaScript
          钩子，开发者可以实现更复杂的动画效果。合理使用过渡和动画可以极大地提升用户体验，使应用更加生动和吸引人
        </h3>
      </transition>
    </div>

    <h3>4. mode属性掌握</h3>
    <div class="animation-container-one">
      <transition name="animation-name-one" mode="out-in">
        <h2 v-if="isShow">在 Vue 3 中，过渡和动画是增强用户体验的重要特性</h2>
        <h2 v-else>钩子，开发者可以实现更复杂的动画效果</h2>
      </transition>
    </div>
    <h3>5. 组件动画</h3>
    <div class="animation-container-one">
      <transition name="animation-name-one" mode="out-in" appear="">
        <component :is="isShow ? Home : About"></component>
      </transition>
    </div>
    <div>
      <button @click="isShow = !isShow">切换</button>
    </div>

    <h2>5. 打乱数字案例动画</h2>
    <div class="animation-container-numbers">
      <button @click="addNumber">添加数字</button>
      <button @click="removeNumber">删除数字</button>
      <button @click="shuffleNumber">打乱数字</button>

      <transition-group tag="div" name="numbers">
        <template v-for="item in nums" :key="item">
          <span>{{ item }}</span>
        </template>
      </transition-group>
    </div>
  </div>
</template>

<script setup>
  import { ref } from "vue";
  import Home from "./pages/Home.vue";
  import About from "./pages/About.vue";

  import { shuffle } from "underscore";

  const nums = ref([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

  const isShow = ref(false);

  const addNumber = () => {
    nums.value.splice(randomIndex(), 0, nums.value.length);
  };

  const removeNumber = () => {
    nums.value.splice(randomIndex(), 1);
  };

  const shuffleNumber = () => {
    nums.value = shuffle(nums.value);
  };

  const randomIndex = () => {
    return Math.floor(Math.random() * nums.value.length);
  };
</script>

<style lang="scss" scoped>
  .transition-container {
    // xxx-enter-from: 动画进入之前
    // xxx-enter-active: 动画进入中
    // xxx-enter-to: 动画进入之后

    // xxx-leave-from: 动画离开之前
    // xxx-leave-active: 动画离开中
    // xxx-leave-to: 动画离开之后
    .transition-name-enter-from,
    .transition-name-leave-to {
      opacity: 0;
      transform: scale(0.7);
    }

    .transition-name-enter-from,
    .transition-name-leave-to {
      opacity: 1;
      transform: scale(0.1);
    }

    .transition-name-enter-active,
    .transition-name-leave-active {
      transition: all 2.5s ease-in-out;
    }
  }

  .animation-container {
    .animation-name-enter-active {
      animation: EnterAnim 1s ease-in-out;
    }

    .animation-name-leave-active {
      animation: LeaveAnim 1s ease-in-out reverse;
    }

    @keyframes EnterAnim {
      0% {
        transform: scale(0);
        opacity: 0;
      }

      50% {
        transform: scale(1.2);
        opacity: 0.5;
      }

      100% {
        transform: scale(1);
        opacity: 1;
      }
    }

    @keyframes LeaveAnim {
      0% {
        transform: translateX(0);
        opacity: 1;
      }

      100% {
        transform: translateX(-500px);
        opacity: 0;
      }
    }
  }

  .animation-container-one {
    .animation-name-one-enter-from,
    .animation-name-one-leave-to {
      opacity: 0;
    }

    .animation-name-one-enter-to,
    .animation-name-one-leave-from {
      opacity: 1;
    }

    .animation-name-one-enter-active {
      animation: animation-name-oneAnim 2s ease;
      transition: opacity 2s ease;
    }

    .animation-name-one-leave-active {
      animation: animation-name-oneAnim 2s ease reverse;
      transition: opacity 2s ease;
    }

    @keyframes animation-name-oneAnim {
      0% {
        transform: scale(0);
      }

      50% {
        transform: scale(1.2);
      }

      100% {
        transform: scale(1);
      }
    }
  }

  .animation-container-numbers {
    span {
      margin-right: 10px;
      display: inline-block;
    }

    .numbers-enter-from,
    .numbers-leave-to {
      opacity: 0;
      transform: translateY(30px);
    }

    .numbers-enter-to,
    .numbers-leave-from {
      opacity: 1;
      transform: translateY(0);
    }

    .numbers-enter-active,
    .numbers-leave-active {
      transition: all 2s ease;
    }

    .numbers-leave-active {
      position: absolute;
    }

    /* 针对其他移动的阶段需要的动画 */
    .numbers-move {
      transition: all 2s ease;
    }
  }
</style>
